#include<linux/kernel.h>
#include<linux/module.h>
#include<linux/init.h>
#include<linux/types.h>
// #include<asm/desc_defs.h>

// struct desc_ptr {
//     unsigned short size;
//     unsigned long address;
// } __attribute__((packed));

// struct desc_struct {
// 	unsigned short limit0;
// 	unsigned short base0;
// 	unsigned short base1: 8, type: 4, s: 1, dpl: 2, p: 1;
// 	unsigned short limit1: 4, avl: 1, l: 1, d: 1, g: 1, base2: 8;
// } __attribute__((packed));

int init_module(void){
    struct desc_ptr gdtr;
    struct desc_struct *gdt;
    unsigned long base;
    unsigned long limit;
    int i, gdt_size;

    printk(KERN_INFO "task_3\n");
    asm volatile("sgdt %0" : "=m" (gdtr));

    printk(KERN_INFO "GDT Base Address: 0x%lx\n", gdtr.address);
    printk(KERN_INFO "GDT Limit: 0x%x\n", gdtr.size);

    gdt_size = (gdtr.size + 1) / sizeof(struct desc_struct);
    gdt = (struct desc_struct *)gdtr.address;

    for(i = 0; i<gdt_size; i++){
        base = (gdt[i].base0) | (gdt[i].base1 << 16) | (gdt[i].base2 << 24);
        limit = (gdt[i].limit0) | (gdt[i].limit1 << 16);
        if(gdt[i].g){
            limit = (limit<<12) | 0xFFF;
        }

        printk(KERN_INFO "GDT Entry %d: Base Address = 0x%08lx, Limit = 0x%08lx\n", i, base, limit);
    }
    return 0;
}

void cleanup_module(void){
    printk("task_3 end\n");
}